Public Class NameScroller

#Region " properties "

	Public Property Queue() As Queue(Of String)
		Get
			Return _Queue
		End Get
		Set(ByVal value As Queue(Of String))
			_Queue = value
		End Set
	End Property
	Private _Queue As Queue(Of String)


	Public Property Running() As Boolean
		Get
			Return _Running
		End Get
		Set(ByVal value As Boolean)
			_Running = value
		End Set
	End Property
	Private _Running As Boolean


	Public Overrides Property Text() As String
		Get
			Return _Text
		End Get
		Set(ByVal value As String)
			_Text = value
		End Set
	End Property
	Private _Text As String


	' gradient that defines the faded edges 
	Private faded_borders As Drawing.Drawing2D.LinearGradientBrush

	' a bitmap overlay of the faded edges
	Private faded_overlay As Bitmap

#End Region

	Private Const pixel_X_steps As Integer = 20
	Private Const pixel_Y_steps As Integer = 1
	' the top y-offset where a entrancing name should stop
	Private top_limit As Integer = 0
	' the amount of loops to wait before moving onto the exit stage
	Private Const wait_loops As Integer = 100


	Private _x As Integer = 0
	Private _y As Integer = 0
	Private _loop As Integer = 0
	Private _name As String
	Private _action As ActionType = ActionType.None

	Enum ActionType
		None
		Scroll_Entrance
		Scroll_Wait
		Scroll_Exit
	End Enum


	Private Sub Draw_Name(ByVal name As String)
		RenderTimer.Stop()
		_name = name
		_x = 0
		_y = -20
		_loop = 0
		_action = ActionType.Scroll_Entrance
		RenderTimer.Start()
	End Sub


	Sub Start()
		Draw_Name(Queue.Dequeue)
	End Sub


	Private Sub RenderTimer_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles RenderTimer.Tick
		Select Case _action

			Case ActionType.Scroll_Entrance

				If (_y >= top_limit) Then
					' start the wait process
					_loop = wait_loops
					_action = ActionType.Scroll_Wait
				Else
					' keep on moving
					_y += pixel_Y_steps
				End If

			Case ActionType.Scroll_Wait

				' test if our wait is over
				If (_loop <= 0) Then
					_action = ActionType.Scroll_Exit
				Else
					' keep on waiting
					_loop -= 1
				End If

			Case ActionType.Scroll_Exit

				If (_x >= Me.Width) Then
					' start the next name
					If (Queue.Count > 0) Then
						Draw_Name(Queue.Dequeue)
					Else
						' we reached the end!
						RenderTimer.Stop()
					End If
				Else
					' keep on moving
					_x += pixel_X_steps
				End If

		End Select

		' let the control redraw itself
		Me.Invalidate()

	End Sub



	Sub New()

		' This call is required by the Windows Form Designer.
		InitializeComponent()

		Me.SetStyle(ControlStyles.AllPaintingInWmPaint, True)
		Me.SetStyle(ControlStyles.UserPaint, True)
		Me.SetStyle(ControlStyles.OptimizedDoubleBuffer, True)

		Me.Queue = New Queue(Of String)
		Setup_Fader_Brush()

	End Sub


	Private Sub NameScroller_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
		e.Graphics.DrawString(_name, Me.Font, Brushes.Black, _x, _y)
		e.Graphics.DrawImage(faded_overlay, 0, 0)
	End Sub


	Private Sub Setup_Fader_Brush()

		' dispose the previous brush
		If Not IsNothing(faded_borders) Then faded_borders.Dispose()

		' we from opaque to transparant
		Dim transp As Color = Color.FromArgb(0, Me.BackColor)

		' the gradient is half our client area
		Dim rect As Rectangle

		' setup the fade overlay
		faded_overlay = New Bitmap(Me.Width, Me.Height)
		Dim g As Graphics = Graphics.FromImage(faded_overlay)
		g.Clear(Color.Transparent)

		' setup and render the right-edged gradient
		rect = New Rectangle(Me.Width - 40, 0, 40, Me.Height)
		faded_borders = New Drawing2D.LinearGradientBrush(rect, transp, Me.BackColor, Drawing2D.LinearGradientMode.Horizontal)
		g.FillRectangle(faded_borders, faded_borders.Rectangle)

		' setup and render the top-edge gradient
		rect = New Rectangle(0, 0, Me.Width, Me.Height \ 2)
		faded_borders = New Drawing2D.LinearGradientBrush(rect, Me.BackColor, transp, Drawing2D.LinearGradientMode.Vertical)
		g.FillRectangle(faded_borders, faded_borders.Rectangle)

		top_limit = rect.Height - 4

		' clean up the graphics
		g.Dispose()

	End Sub


	Private Sub NameScroller_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Resize
		Setup_Fader_Brush()
	End Sub


End Class
